﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConcreteFactoryPattern
{
    /// <summary>
    /// 抽象产品角色
    /// </summary>
    public interface IAinimal
    {
        void Speak();
    }

    /// <summary>
    /// 具体产品角色
    /// </summary>
    public class Dog : IAinimal
    {
        public void Speak()
        {
            Console.WriteLine("旺旺");
        }

    }


    public class Cat : IAinimal
    {
        public void Speak()
        {
            Console.WriteLine("喵喵");
        }

    }

    /// <summary>
    /// 工厂角色
    /// </summary>
    public class SimpleAinimalFactory
    {
        public IAinimal CreateAinimal(string type)
        {
            if (type.Equals("cat"))
            {
                return new Cat();
            }
            else if (type.Equals("dog"))
            {
                return new Dog();
            }
            else
            {
                throw new Exception("invalid type");
            }
        }
    }


    /// <summary>
    /// 抽象工厂
    /// </summary>
    public interface IAinimalFactory
    {
        IAinimal CreateAinimal();
    }

    /// <summary>
    /// 具体工厂
    /// </summary>
    public class CatAinimalFactory : IAinimalFactory
    {
        public IAinimal CreateAinimal()
        {
            return new Cat();
        }
    }


    public class DogAinimalFactory : IAinimalFactory
    {
        public IAinimal CreateAinimal()
        {
            return new Dog();
        }
    }



    /// <summary>
    /// 工厂方法模式的主要角色：

    ///    抽象工厂（Abstract Factory）：提供了创建产品的接口，调用者通过它访问具体工厂的工厂 方法来创建产品。
    ///    具体工厂（ConcreteFactory）：主要是实现抽象工厂中的抽象方法，完成具体产品的创建。
    ///    抽象产品（Product）：定义了产品的规范，描述了产品的主要特性和功能。
    ///    具体产品（ConcreteProduct）：实现了抽象产品角色所定义的接口，由具体工厂来创建，它同 具体工厂之间一一对应。
    ///    抽象产品和具体产品同上不变，将工厂角色抽出来，改成抽象工厂+具体工厂
    /// 
    /// 
    /// 
    /// 与简单工厂不同的地方就是这边先获取一个对应的具体工厂，再通过具体工厂拿到具体产品。在使用时，用于只需知道产品对应的具体工厂，
    /// 关注具体的创建过程，甚至不需要知道具体产品类的类名，当我们选择哪个具体工厂时，就已经决定了实际创建的产品是哪个了。
    /// </summary>

    class Program
    {
        static void Main(string[] args)
        {

        }
    }
}
